#include "Camera.h"
#include <glm/gtc/matrix_transform.hpp>


Camera::Camera(const U32 &width, const U32 &height)
{
	perspective(45.0f, (float)width/(float)height, 1.0f, 20000.0f);
	viewMatrix = glm::mat4(1.0f);
	position = glm::vec3(0.0f);
	fwdDir = glm::vec3(0.0f, 0.0f, 1.0f);
	leftDir = glm::vec3(1.0f, 0.0f, 0.0f);
	upDir = glm::vec3(0.0f, 1.0f, 0.0f);
}

Camera::~Camera()
{
}

const glm::mat4 &Camera::perspective(float fovY, float aspect, float zNear, float zFar)
{
	projMatrix = glm::gtc::matrix_transform::perspective<F32>(fovY, aspect, zNear, zFar);
	return projMatrix;
}

void Camera::prepare()
{
	// Calculate the translation matrix using the local position vector
	glm::mat4 translate = glm::mat4(1.0f);
	translate[3][0] = position.x;
	translate[3][1] = position.y;
	translate[3][2] = position.z;

	glm::mat4 rotation = glm::gtc::quaternion::mat4_cast(qRotation);

	// Then, we calculate the local transformation matrix
	viewMatrix = glm::mat4(1.0f);
	//viewMatrix *= scale;
	viewMatrix *= rotation;
	viewMatrix *= translate;
}

void Camera::rotate(F32 angle, glm::vec3 axis)
{
	if(axis.x)
		qRotation = glm::gtc::quaternion::rotate(qRotation, angle, leftDir*glm::vec3(-1,-1,1)*axis.x);
	else if(axis.y)
		qRotation = glm::gtc::quaternion::rotate(qRotation, angle, upDir*axis.y);
	else if(axis.z)
		qRotation = glm::gtc::quaternion::rotate(qRotation, angle, fwdDir*glm::vec3(-1,-1,1)*axis.z);
	fwdDir = qRotation * glm::vec3(0.0f, 0.0f, 1.0f);
	leftDir = qRotation * glm::vec3(-1.0f, 0.0f, 0.0f);
	upDir = qRotation * glm::vec3(0.0f, 1.0f, 0.0f);
}

void Camera::translate(F32 x, F32 y, F32 z)
{
	position += glm::vec3(x,y,z);
}

void  Camera::forward(F32 value)
{
	position += (fwdDir * glm::vec3(-1,-1,1)) * value;
}

void  Camera::left(F32 value)
{
	position += (leftDir * glm::vec3(-1,-1,1)) * value;
}

void  Camera::up(F32 value)
{
	position += (upDir * glm::vec3(-1,-1,1)) * value;
}
